package com.miyake.dsp.osa.realinstrument;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang.ArrayUtils;

import com.miyake.dsp.analyzer.PeakSearchCommon;
import com.miyake.dsp.common.CommonTool;
import com.miyake.dsp.common.UnitConverter;

public class HigeSearch {

	public List<Integer> getPeakIndexes() {
		return peakIndexes;
	}

	public double getPeakSearchFloor() {
		return peakSearchFloor;
	}

	private double[] data;
	private List<Integer> higeIndexs = new ArrayList<Integer>();
	private List<Double> higeValues = new ArrayList<Double>();
	private double noiseLevel;
	private double peakSearchFloor;
	private List<Integer> peakIndexes;
	
	public HigeSearch(double[] data) {
		this.data = data;
		PeakSearchCommon peakSearch = new PeakSearchCommon(this.data);
		noiseLevel = peakSearch.getNoiseLevel();
		initialize(peakSearch);
		
	}
	
	public HigeSearch(double[] data, double noiseLevel)  {
//		if (data[0] < -10.0) {
//			this.data = UnitConverter.toW(data);
//		}
//		else {
			this.data = data;
//		}
		this.noiseLevel = noiseLevel;
		PeakSearchCommon peakSearch = new PeakSearchCommon(this.data, noiseLevel);
		initialize(peakSearch);
	}
	private void initialize(PeakSearchCommon peakSearch) {
		peakSearchFloor = peakSearch.getNoiseLevel();
		peakIndexes = peakSearch.getPeakInexes();
		int[] ins = ArrayUtils.toPrimitive(peakSearch.getPeakInexes().toArray(new Integer[0]));
//		higeIndexs = peakSearch.getPeakInexes();
		
		if (ins.length > 1) {
			for (int i = 0; i < ins.length; i++) {
				if (i == 0) {
					searchHige(ins[0] - (ins[1] - ins[0])/2, (ins[i] + ins[i+1])/2, ins[i]);
				}
				else if (i == ins.length-1) {
					searchHige((ins[i] + ins[i-1])/2, ins[i] + (ins[i] - ins[i-1])/2, ins[i]);
				}
				else {
					searchHige((ins[i] + ins[i-1])/2, (ins[i] + ins[i+1])/2, ins[i]);
				}
			}
		}
		else if (ins.length == 1){
			searchHige(0, this.data.length-1, ins[0]);
		}
	}

	
	private void searchHige(int start, int end, int peak) {
		if (start < 0) {
			start = 0;
		}
		if (end > data.length-1) {
			end = data.length -1;
		}
		double[] diff = CommonTool.getDiff(data);
		for (int i = start; i  < peak; i++) {
			if (diff[i] < 0 && data[i] > noiseLevel && ((data[peak] - data[i]) > 2)) {
				addHige(i, diff[i]);
			}
		}
		for (int i = peak; i < end; i++) {
			if (diff[i] > 0 && data[i] > noiseLevel && ((data[peak] - data[i]) > 2)) {
				addHige(i, diff[i]);
			}
		}
	}

	private void addHige(int i, double value) {
		this.higeIndexs.add(i);
		this.higeValues.add(value);
	}
	
	public int[] getHigeIndexes() {
		return ArrayUtils.toPrimitive(this.higeIndexs.toArray(new Integer[0]));
	}
	
	public double[] getHigeValues() {
		return ArrayUtils.toPrimitive(this.higeValues.toArray(new Double[0]));
	}
}
